package dao

import (
	"context"
	"fmt"
	"gitee.com/hxchjm/go-admin/internal/models"
	"gitee.com/hxchjm/go-admin/pkg/db"
	"github.com/hxchjm/log"
	"github.com/jinzhu/copier"
	"github.com/pkg/errors"
	"gorm.io/gorm"
)

type SysDept struct {
	models.SysDept
}

//func (*SysDept) TableName() string {
//	return "sys_dept"
//	//return fmt.Sprintf("%s.sys_dept", db.GetDBName())
//}

func (e *SysDept) GetId() interface{} {
	return e.DeptId
}

// Get 获取SysDept对象
func (e SysDept) Get(ctx context.Context) (*SysDept, error) {
	var model SysDept
	if err := db.GetDB().Model(&e).First(&model, e.DeptId).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			err = errors.New("查看对象不存在或无权查看")
		}
		return nil, err
	}
	return &model, nil
}

// Insert 创建SysDept对象
func (e *SysDept) Insert(ctx context.Context) error {
	var err error
	tx := db.GetDB().WithContext(ctx).Debug().Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	err = tx.Create(&e).Error
	if err != nil {
		log.Errorf(ctx, "db error:%s", err)
		return err
	}
	deptPath := fmt.Sprintf("%d/", e.DeptId)
	if e.ParentId != 0 {
		var deptP models.SysDept
		tx.First(&deptP, e.ParentId)
		deptPath = deptP.DeptPath + deptPath
	} else {
		deptPath = "/0/" + deptPath
	}
	if err = tx.Model(&e).Update("dept_path", deptPath).Error; err != nil {
		log.Errorf(ctx, "db error:%s", err)
		return err
	}
	return nil
}

// Update 修改SysDept对象
func (e SysDept) Update(ctx context.Context) error {
	var err error
	var model = SysDept{}
	tx := db.GetDB().WithContext(ctx).Debug().Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	tx.First(&model, e.DeptId)
	_ = copier.CopyWithOption(&model, e, copier.Option{IgnoreEmpty: true})
	deptPath := fmt.Sprintf("%d/", model.DeptId)
	if model.ParentId != 0 {
		var deptP models.SysDept
		tx.First(&deptP, model.ParentId)
		deptPath = deptP.DeptPath + deptPath
	} else {
		deptPath = "/0/" + deptPath
	}
	model.DeptPath = deptPath
	d := tx.Save(&model)
	if err = d.Error; err != nil {
		log.Errorf(ctx, "UpdateSysDept error:%s", err)
		return err
	}
	if d.RowsAffected == 0 {
		return errors.New("无权更新该数据")
	}
	return nil
}

// Delete 删除SysDept
func (e SysDept) Delete(ctx context.Context) error {
	var err error
	var data models.SysDept

	tx := db.GetDB().WithContext(ctx).Model(&data).Delete(&data, e.DeptId)
	if err = tx.Error; err != nil {
		log.Errorf(ctx, "Delete error: %s", err)
		return err
	}
	if tx.RowsAffected == 0 {
		err = errors.New("无权删除该数据")
		return err
	}
	return nil
}

// GetSysDeptList 获取组织数据
func (e SysDept) getList(ctx context.Context) ([]models.SysDept, error) {
	var list []models.SysDept
	if err := db.GetDB().WithContext(ctx).Model(models.SysDept{}).Find(&list).Error; err != nil {
		log.Errorf(ctx, "db error:%s", err)
		return nil, err
	}
	return list, nil
}

// SetDeptTree 设置组织数据
func (e SysDept) SetDeptTree(ctx context.Context) (m []models.DeptLabel, err error) {
	list, err := e.getList(ctx)

	m = make([]models.DeptLabel, 0)
	for i := 0; i < len(list); i++ {
		if list[i].ParentId != 0 {
			continue
		}
		e := models.DeptLabel{}
		e.Id = list[i].DeptId
		e.Label = list[i].DeptName
		deptsInfo := deptTreeCall(&list, e)

		m = append(m, deptsInfo)
	}
	return
}

// Call 递归构造组织数据
func deptTreeCall(deptList *[]models.SysDept, dept models.DeptLabel) models.DeptLabel {
	list := *deptList
	min := make([]models.DeptLabel, 0)
	for j := 0; j < len(list); j++ {
		if dept.Id != list[j].ParentId {
			continue
		}
		mi := models.DeptLabel{Id: list[j].DeptId, Label: list[j].DeptName, Children: []models.DeptLabel{}}
		ms := deptTreeCall(deptList, mi)
		min = append(min, ms)
	}
	dept.Children = min
	return dept
}

// SetDeptPage 设置dept页面数据
func (e SysDept) SetDeptPage(ctx context.Context) (m []models.SysDept, err error) {
	list, err := e.getList(ctx)
	for i := 0; i < len(list); i++ {
		if list[i].ParentId != 0 {
			continue
		}
		info := e.deptPageCall(&list, list[i])
		m = append(m, info)
	}
	return
}

func (e *SysDept) deptPageCall(deptlist *[]models.SysDept, menu models.SysDept) models.SysDept {
	list := *deptlist
	min := make([]models.SysDept, 0)
	for j := 0; j < len(list); j++ {
		if menu.DeptId != list[j].ParentId {
			continue
		}
		mi := models.SysDept{}
		mi.DeptId = list[j].DeptId
		mi.ParentId = list[j].ParentId
		mi.DeptPath = list[j].DeptPath
		mi.DeptName = list[j].DeptName
		mi.Sort = list[j].Sort
		mi.Leader = list[j].Leader
		mi.Phone = list[j].Phone
		mi.Email = list[j].Email
		mi.Status = list[j].Status
		mi.CreatedAt = list[j].CreatedAt
		mi.Children = []models.SysDept{}
		ms := e.deptPageCall(deptlist, mi)
		min = append(min, ms)
	}
	menu.Children = min
	return menu
}

// GetWithRoleId 获取角色的部门ID集合
func (e *SysDept) GetWithRoleId(roleId int) ([]int, error) {
	deptIds := make([]int, 0)
	deptList := make([]models.DeptIdList, 0)
	if err := db.GetDB().Table("sys_role_dept").
		Select("sys_role_dept.dept_id").
		Joins("LEFT JOIN sys_dept on sys_dept.dept_id=sys_role_dept.dept_id").
		Where("role_id = ? ", roleId).
		Where(" sys_role_dept.dept_id not in(select sys_dept.parent_id from sys_role_dept LEFT JOIN sys_dept on sys_dept.dept_id=sys_role_dept.dept_id where role_id =? )", roleId).
		Find(&deptList).Error; err != nil {
		return nil, err
	}
	for i := 0; i < len(deptList); i++ {
		deptIds = append(deptIds, deptList[i].DeptId)
	}
	return deptIds, nil
}

func (e *SysDept) SetDeptLabel() (m []models.DeptLabel, err error) {
	list := make([]models.SysDept, 0)
	err = db.GetDB().Find(&list).Error
	if err != nil {
		log.Error("find dept list error, %s", err.Error())
		return
	}
	m = make([]models.DeptLabel, 0)
	var item models.DeptLabel
	for i := range list {
		if list[i].ParentId != 0 {
			continue
		}
		item = models.DeptLabel{}
		item.Id = list[i].DeptId
		item.Label = list[i].DeptName
		deptInfo := deptLabelCall(&list, item)
		m = append(m, deptInfo)
	}
	return
}

// deptLabelCall
func deptLabelCall(deptList *[]models.SysDept, dept models.DeptLabel) models.DeptLabel {
	list := *deptList
	var mi models.DeptLabel
	min := make([]models.DeptLabel, 0)
	for j := 0; j < len(list); j++ {
		if dept.Id != list[j].ParentId {
			continue
		}
		mi = models.DeptLabel{Id: list[j].DeptId, Label: list[j].DeptName, Children: []models.DeptLabel{}}
		ms := deptLabelCall(deptList, mi)
		min = append(min, ms)
	}
	dept.Children = min
	return dept
}
